home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 242 / Issue 242 - April 2008 - DPCS0408DVD.ISO / Software Money Savers / VirtualDub / Source / VirtualDub-1.7.7-src.7z / src / Asuka / source / mapconv.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2007-10-13  |  7.4 KB  |  306 lines

  1. //    Asuka - VirtualDub Build/Post-Mortem Utility
  2. //    Copyright (C) 2005 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include "stdafx.h"
  19. #include <vector>
  20. #include <algorithm>
  21.  
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <string.h>
  25.  
  26. #include <vd2/system/vdalloc.h>
  27. #include <vd2/system/VDString.h>
  28. #include <vd2/system/text.h>
  29. #include <vd2/system/vdstl.h>
  30.  
  31. #include "symbols.h"
  32. #include "utils.h"
  33.  
  34. vdfastvector<char> fnambuf;
  35. vdfastvector<char> cnambuf;
  36.  
  37. ///////////////////////////////////////////////////////////////////////////
  38.  
  39. void parsename(sint64 rva, char *buf0) {
  40.     char *buf = buf0;
  41.     char *func_name = NULL;
  42.     char *class_name = NULL;
  43.     char c;
  44.     int special_func = 0;
  45.  
  46.     if (*buf++ != '?') {
  47.         func_name = buf;
  48.     } else {
  49.  
  50.         if (*buf == '?') {
  51.             // ??0
  52.             // ??1
  53.             // ??_G
  54.             // ??_E
  55.  
  56.             ++buf;
  57.             c=*buf++;
  58.  
  59.             special_func = 31;
  60.             if (c=='0')
  61.                 special_func = 1;        // constructor
  62.             else if (c=='1')
  63.                 special_func = 2;        // destructor
  64.             else if (c=='_') {
  65.                 c = *buf++;
  66.  
  67.                 if (c == 'G')
  68.                     special_func = 3;        // scalar deleting destructor
  69.                 else if (c == 'E')
  70.                     special_func = 4;        // vector deleting destructor?
  71.             }
  72.         } else {
  73.             func_name = buf;
  74.  
  75.             while(*buf != '@') {
  76.                 if (!*buf) {
  77.                     printf("    unrecognizable name: %s\n", buf0);
  78.                     throw "bad decorated name";
  79.                 }
  80.  
  81.                 ++buf;
  82.             }
  83.  
  84.             if (buf == func_name)
  85.                 printf("    warning: empty function name generated from: '%s'\n", func_name);
  86.  
  87.             *buf++ = 0;
  88.         }
  89.  
  90.         // Look for a class name.
  91.  
  92.         if (*buf != '@') {
  93.             if (!*buf) {
  94.                 printf("    unrecognizable name: %s\n", buf0);
  95.                 throw "bad decorated name";
  96.             }
  97.  
  98.             class_name = buf;
  99.  
  100.             while(*buf != '@') {
  101.                 if (!*buf)
  102.                     throw "bad decorated name (class)";
  103.  
  104.                 ++buf;
  105.             }
  106.  
  107.             if (buf == class_name)
  108.                 printf("    warning: empty class name generated from: '%s'\n", class_name);
  109.  
  110.             *buf++ = 0;
  111.         }
  112.     }
  113.  
  114.     // write out to buffers
  115.  
  116.     if (class_name) {
  117.         int idx = 0;
  118.         bool found = false;
  119.  
  120.         if (!cnambuf.empty()) {
  121.             char *csptr = &cnambuf[0];
  122.             char *csend = csptr + cnambuf.size();
  123.             while(csptr < csend) {
  124.                 if (!strcmp(csptr, class_name)) {
  125.                     found = true;
  126.                     break;
  127.                 }
  128.                 while(*csptr++);
  129.                 ++idx;
  130.             }
  131.         }
  132.  
  133.         if (!found)
  134.             cnambuf.insert(cnambuf.end(), class_name, class_name + strlen(class_name) + 1);
  135.  
  136.         fnambuf.push_back(1 + (idx / 128));
  137.         fnambuf.push_back(1 + (idx % 128));
  138.  
  139.         if (special_func)
  140.             fnambuf.push_back(special_func);
  141.     }
  142.  
  143.     if (func_name) {
  144.         if (!*func_name)
  145.             printf("    warning: writing out empty function name\n");
  146.         fnambuf.insert(fnambuf.end(), func_name, func_name + strlen(func_name) + 1);
  147.     } else {
  148.         if (!class_name)
  149.             printf("    warning: function name absent: '%s'\n", buf);
  150.         fnambuf.push_back(0);
  151.     }
  152. }
  153.  
  154. void VDNORETURN help_mapconv() {
  155.     printf("usage: mapconv <listing-file> <output-name> <disassembler module>\n");
  156.     exit(5);
  157. }
  158.  
  159. void tool_mapconv(const vdfastvector<const char *>& args, const vdfastvector<const char *>& switches, bool amd64) {
  160.     FILE *fo;
  161.     int i;
  162.  
  163.     if (args.size() < 3)
  164.         help_mapconv();
  165.  
  166.     // Begin parsing file
  167.  
  168.     vdautoptr<IVDSymbolSource> syms(VDCreateSymbolSourceLinkMap());
  169.     vdfastvector<VDSymbol> rvabuf;
  170.     syms->Init(VDTextAToW(args[0]).c_str());
  171.  
  172.     if (!(fo=fopen(args[1], "wb")))
  173.         fail("    can't open output file \"%s\"\n", args[1]);
  174.  
  175.     int disasm_size = 0;
  176.     {
  177.         FILE *fd;
  178.  
  179.         if (!(fd=fopen(args[2], "rb")))
  180.             fail("    can't open disassembler module \"%s\"\n", args[2]);
  181.  
  182.         void *buf = malloc(32768);
  183.         int act;
  184.  
  185.         while((act = fread(buf, 1, 32768, fd)) > 0) {
  186.             disasm_size += act;
  187.             fwrite(buf, act, 1, fo);
  188.         }
  189.  
  190.         free(buf);
  191.         fclose(fd);
  192.     }
  193.  
  194.     // delete all entries that take no space -- these often crop up with inline classes
  195.  
  196.     const uint32 code_segs(syms->GetCodeGroupMask());
  197.  
  198.     printf("%x\n", code_segs);
  199.  
  200.     syms->GetAllSymbols(rvabuf);
  201.  
  202.     int j=0;
  203.     for(i=0; size_t(i)<rvabuf.size()-1; ++i) {
  204.         VDSymbol& sym = rvabuf[i];
  205.  
  206.         if (!(code_segs & (1<<sym.group)))
  207.             continue;
  208.  
  209.         if (!strncmp(sym.name, "__ehhandler$", 12) || !strncmp(sym.name, "__unwindfunclet$", 16))
  210.             continue;
  211.  
  212.         if (rvabuf[i+1].rva - sym.rva) {
  213.             rvabuf[j++] = sym;
  214.         }
  215.     }
  216.     rvabuf[j++] = rvabuf[i];    // last entry is always copied
  217.  
  218.     printf("    Deleted %d zero-size and EH stub entries from RVA table\n", i+1-j);
  219.     rvabuf.resize(j);
  220.  
  221.     size_t rvabufsize = rvabuf.size();
  222.     for(i=0; size_t(i)<rvabufsize; i++) {
  223.         VDSymbol& sym = rvabuf[i];
  224.  
  225.         parsename(sym.rva, sym.name);
  226.     }
  227.     
  228.     int segcnt = syms->GetSectionCount();
  229.     vdfastvector<uint32> segbuf(segcnt * 2);
  230.     for(i=0; i<segcnt; i++) {
  231.         const VDSection *sect = syms->GetSection(i);
  232.         segbuf[i*2+0] = (uint32)(sect->mAbsStart);
  233.         segbuf[i*2+1] = sect->mLength;
  234.         printf("        #%-2d  %08lx-%08lx\n", i+1, sect->mStart, sect->mStart + sect->mLength - 1);
  235.     }
  236.  
  237.     printf("        Raw statistics:\n");
  238.     printf("            Disassembler:     %ld bytes\n", disasm_size);
  239.     printf("            RVA bytes:        %ld\n", rvabuf.size()*4);
  240.     printf("            Class name bytes: %ld\n", cnambuf.size());
  241.     printf("            Func name bytes:  %ld\n", fnambuf.size());
  242.  
  243.     printf("    Packing RVA data..."); fflush(stdout);
  244.  
  245.     vdfastvector<VDSymbol>::iterator itRVA = rvabuf.begin(), itRVAEnd = rvabuf.end();
  246.     vdfastvector<char> rvaout;
  247.     sint64 firstrva = (*itRVA++).rva;
  248.     sint64 lastrva = firstrva;
  249.  
  250.     for(; itRVA != itRVAEnd; ++itRVA) {
  251.         sint64 rvadiff = (*itRVA).rva - lastrva;
  252.  
  253.         lastrva += rvadiff;
  254.  
  255.         if (rvadiff & 0xF0000000) rvaout.push_back((char)(0x80 | ((rvadiff>>28) & 0x7F)));
  256.         if (rvadiff & 0xFFE00000) rvaout.push_back((char)(0x80 | ((rvadiff>>21) & 0x7F)));
  257.         if (rvadiff & 0xFFFFC000) rvaout.push_back((char)(0x80 | ((rvadiff>>14) & 0x7F)));
  258.         if (rvadiff & 0xFFFFFF80) rvaout.push_back((char)(0x80 | ((rvadiff>> 7) & 0x7F)));
  259.         rvaout.push_back((char)(rvadiff & 0x7F));
  260.     }
  261.  
  262.     printf("%ld bytes\n", rvaout.size());
  263.  
  264.     // dump data
  265.  
  266.     long t;
  267.  
  268.     static const char header[64]="[01|01] VirtualDub symbolic debug information\r\n\x1A";
  269.  
  270.     fwrite(header, 64, 1, fo);
  271.  
  272.     t = get_version();
  273.     fwrite(&t, 4, 1, fo);
  274.  
  275.     t = rvaout.size() + 4;
  276.     fwrite(&t, 4, 1, fo);
  277.  
  278.     t = cnambuf.size();
  279.     fwrite(&t, 4, 1, fo);
  280.  
  281.     t = fnambuf.size();
  282.     fwrite(&t, 4, 1, fo);
  283.  
  284.     t = segcnt;
  285.     fwrite(&t, 4, 1, fo);
  286.  
  287.     fwrite(&firstrva, 4, 1, fo);
  288.     fwrite(rvaout.data(), rvaout.size(), 1, fo);
  289.     fwrite(cnambuf.data(), cnambuf.size(), 1, fo);
  290.     fwrite(fnambuf.data(), fnambuf.size(), 1, fo);
  291.     fwrite(segbuf.data(), segcnt*8, 1, fo);
  292.  
  293.     // really all done
  294.  
  295.     if (fclose(fo))
  296.         throw "output file close failed";
  297.  
  298.     FILE *fLock = fopen("autobuild.lock", "r");
  299.     if (fLock) {
  300.         fclose(fLock);
  301.     } else {
  302.         inc_version();
  303.         write_version();
  304.     }
  305. }
  306.